package com.free.semantic.core.impl.demo.sample.memoryStoreImpl;

import com.free.semantic.common.Ls;
import com.free.semantic.common.RangeObj;
import com.free.semantic.common.RelationChain;
import com.free.semantic.common.RelationItem;
import com.free.semantic.core.ConceptManage;
import com.free.semantic.core.Context;
import com.free.semantic.core.FunctionProvider;
import com.free.semantic.core.RelationFunction;
import com.free.semantic.utils.Utils;
import lombok.Data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DefaultMemoryConceptInstanceImpl implements FunctionProvider {


    private ConceptManage conceptManage;

    private Map<String, EntityMetaInfo> entityMetaInfo = new HashMap<>();

    private Map<String, Map<Long, Map<String, Object>>> entityDataStorage = new HashMap<>();

    private Map<RelationItem, RelationFunction> functionMap = new HashMap<>();

    @Data
    private static class EntityMetaInfo {

        private String entityName;

        private Map<String, String> fieldTypeInfo;

        private Long currentId;

    }


    /***
     *  RelationDefineGroup group = new RelationDefineGroup();
     *         object(conceptManage, "BaseConcept");
     *         object(conceptManage, "BaseEntity");
     *         object(conceptManage, "create");
     *         object(conceptManage, "update");
     *         object(conceptManage, "delete");
     *         defineRelation(group, "属性",
     *                 defineItem(oneObj("A"), oneObj("B"))); //A->B=[0,) //代表 针对任意一个A，都可以找到 [0,)个B与之对应
     *         defineRelation(group, "查询属性",
     *                 defineItem(oneObj("B"), moreObj("A"))); //A->B=[0,) //代表 针对任意一个A，都可以找到 [0,)个B与之对应
     *         defineRelation(group, "关联单据",
     *                 defineItem(oneObj("A"), oneObj("B"))); //A->B=[0,) //代表 针对任意一个A，都可以找到 [0,)个B与之对应
     * @param conceptManage
     */
    public DefaultMemoryConceptInstanceImpl(ConceptManage conceptManage) {
        this.conceptManage = conceptManage;

        List<String> allObjects = conceptManage.getAllObjects();
        for (String currentObj : allObjects) {
            if (is(currentObj, "entity")) {
                if ("entity".equals(currentObj)) {
                    continue;
                }
                buildEntity(currentObj);
            }
        }
    }

    private void buildEntityCreateAction(String conceptName) {
        List<String> entityName = conceptManage.findAllConnectByRelation(Ls.of(conceptName), "关联单据");

        if (entityName.size() != 1) {
            throw new RuntimeException(String.format("%s没有使用关联单据关系关联 实体，无法找到实体名称", conceptName));
        }


    }

    private Long getId(String name) {
        EntityMetaInfo metaInfo = entityMetaInfo.get(name);
        metaInfo.currentId++;
        return metaInfo.currentId;
    }


    private void registerFunction(List<String> src, String dest, RelationFunction function) {
        List<RelationChain> relationChains = conceptManage.findExactRelationChain(src, dest);
        RelationItem relationItem = relationChains.get(0).toRelationItem();
        functionMap.put(relationItem, function);
    }


    private void buildEntity(String entityName) {

        String conceptName = entityName + "_concept";

        String createAction = entityName + "_create";

        String updateAction = entityName + "_update";

        String deleteAction = entityName + "_delete";

        conceptManage.addConcept(conceptName, createAction, updateAction, deleteAction);

        List<String> allAttr = conceptManage.findAllConnectByRelation(Ls.of(entityName), "属性");

        EntityMetaInfo metaInfo = new EntityMetaInfo();
        metaInfo.entityName = entityName;
        metaInfo.currentId = 0L;

        Map<String, String> fieldTypeInfo = new HashMap<>();


        List<String> allSource = new ArrayList<>(allAttr);
        allSource.add(conceptName);

        {
            List<String> all = new ArrayList<>(allSource);
            all.add(createAction);
            // 添加 新增函数
            Utils.createRelation2(conceptManage, "关联4", all.toArray(new String[0]));

            // 实现新增函数
            registerFunction(allSource, createAction, context -> {
                Map<String, Object> value = new HashMap<>();
                for (String attr : allAttr) {
                    value.put(attr, context.getListValue(attr).get(0));
                }
                Long id = getId(entityName);
                entityDataStorage.get(entityName).put(id, value);
                context.setValue(createAction, true);

            });
        }

//        {
//
//            List<String> all = new ArrayList<>(allAttr);
//            all.add(entityName);
//            all.add(updateAction);
//            // 添加 更新函数
//            Utils.createRelation2(conceptManage, "lessOne4", all.toArray(new String[0]));
//
//            List<String> all2 = new ArrayList<>(allAttr);
//            all2.add(entityName);
//            // 实现更新函数
//            registerFunction(all2, updateAction, context -> {
//                Long id = (Long) context.getListValue(entityName).get(0);
//                if (!entityDataStorage.get(entityName).containsKey(id)) {
//                    throw new RuntimeException(String.format("不存在id是%d的对象", id));
//                }
//                for (String attr : allAttr) {
//                    List<Object> listValue = context.getListValue(attr);
//                    if (listValue != null && listValue.size() > 0) {
//                        entityDataStorage.get(entityName).get(id).put(attr, listValue.get(0));
//                    }
//                }
//                context.setValue(createAction, true);
//            });
//
//        }


        {
            // 添加 删除函数
            Utils.createRelation(conceptManage, "多个找到", entityName, deleteAction);

            registerFunction(Ls.of(entityName), deleteAction, context -> {
                List<Long> listValue1 = context.getListValue(entityName);
                for (Long id : listValue1) {
                    entityDataStorage.get(entityName).remove(id);
                }
                context.setValue(deleteAction, true);
            });
        }

        {
            // 添加 通用查询函数
            Utils.createRelation(conceptManage, "找到多个", "pageParam", entityName);
            registerFunction(Ls.of("pageParam"), entityName, context -> {
                List<Long> idList = new ArrayList<>(entityDataStorage.get(entityName).keySet());
                context.setValue(entityName, idList);
            });
        }


        for (String attr : allAttr) {
            if (is(attr, "entity")) {
                String type = conceptManage.findAllConnectByRelation(Ls.of(attr), "是").get(0);
                fieldTypeInfo.put(attr, type);
            } else {
                fieldTypeInfo.put(attr, "string");
            }
            //添加属性查询函数
            registerFunction(Ls.of(entityName), attr, new RelationFunction() {
                @Override
                public void calculate(Context context) {
                    Long val = (Long) context.getListValue(entityName).get(0);
                    context.setValue(attr, entityDataStorage.get(entityName).get(val).get(attr));
                }
            });
        }
        metaInfo.fieldTypeInfo = fieldTypeInfo;
        entityMetaInfo.put(entityName, metaInfo);
        entityDataStorage.put(entityName, new HashMap<>());

    }

    private boolean is(String objectName, String destName) {
        List<RelationChain> relationChains = conceptManage.findExactRelationChain(Ls.of(objectName), destName);
        if (relationChains.size() != 1) {
            return false;
        }
        List<RelationItem> relationItems = relationChains.get(0).getRelationItems();

        if (relationItems.size() != 1) {
            return false;
        }
        List<RangeObj> sourceObjectList = relationItems.get(0).getSourceObjectList();
        RangeObj destObject = relationItems.get(0).getDestObject();
        if (sourceObjectList.size() != 1 || destObject == null) {
            return false;
        }
        return sourceObjectList.get(0).getObjectName().equals(objectName) && destObject.getObjectName().equals(destName);
    }

    @Override
    public RelationFunction getFunction(RelationItem relationItem) {
        return functionMap.get(relationItem);
    }


}
